package com.xhp.xtool.util.ftp;

import cn.hutool.core.date.DateUtil;
import com.xhp.xtool.domain.FileVo;
import com.xhp.xtool.domain.FtpDto;
import org.apache.commons.net.ftp.FTPClient;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * FTP工具类
 *
 * @author XHP
 * @date 2020年8月14日
 */
@Component
public class FtpUtil {

    /**
     * 接收扫描已改名文件包的FTP连接池
     */
    private volatile static FtpClientPool ftpPool;

    /**
     * 生成连接池
     * <p>
     * 说明：使用连接池是为了保持和真实项目里的连接方式保持一致；因每次连接都是前台传参，所以不能用同一连接池，因此每次返回新连接池
     *
     * @param ftp
     * @return
     */
    public static FtpClientPool getFtpPool(FtpDto ftp) {
        FtpConfig receiveFtpConfig = new FtpConfig();
        receiveFtpConfig.setHost(ftp.getIp());
        receiveFtpConfig.setPort(ftp.getPort());
        receiveFtpConfig.setUserName(ftp.getUserName());
        receiveFtpConfig.setPassWord(ftp.getPassWord());
        receiveFtpConfig.setMaxTotal(10);
        receiveFtpConfig.setMinIdle(1);
        receiveFtpConfig.setMaxIdle(3);
        ftpPool = new FtpClientPool(new FtpClientFactory(receiveFtpConfig));
        return ftpPool;
    }

    public static FtpClientPool getFtpPool() {
        if (ftpPool == null) {
            throw new RuntimeException("无可用连接，请先测试连接");
        }
        return ftpPool;
    }

    /**
     * 上传文件
     *
     * @param pool ftp连接池
     * @param file 待上传文件
     * @return
     * @author XHP
     * @date 2020年8月14日 上午11:25:46
     */
    public static boolean upload(FtpClientPool pool, File file) throws Exception {
        return upload(pool, "/", file);
    }

    /**
     * 上传文件
     *
     * @param pool    ftp连接池
     * @param ftpPath ftp目录
     * @param file    待上传文件
     * @return
     * @author XHP
     * @date 2020年8月14日 上午11:26:15
     */
    public static boolean upload(FtpClientPool pool, String ftpPath, File file) throws Exception {
        FTPClient ftpClient = pool.getFtpClient();
        if (ftpClient != null) {
            // 开始进行文件上传
            try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) {
                ftpClient.enterLocalPassiveMode();
                // 修改文件路径
                ftpClient.makeDirectory(ftpPath);
                ftpClient.changeWorkingDirectory(ftpPath);
                // 执行文件传输
                return ftpClient.storeFile(file.getName(), bis);
            } catch (Exception e) {
                throw new RuntimeException(e);
//                e.printStackTrace();
//                return false;
            } finally {// 关闭资源
                pool.returnFTPClient(ftpClient);
            }
        }
        return false;
    }

    public static int getState(FtpClientPool pool) throws Exception {
        FTPClient ftpClient = pool.getFtpClient();
        if (ftpClient != null) {
            // 开始进行文件上传
            try {
                ftpClient.enterLocalPassiveMode();
                return ftpClient.getReplyCode();
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {// 关闭资源
                pool.returnFTPClient(ftpClient);
            }
        }
        throw new RuntimeException("无可用连接，请先测试连接");
    }

    public static List<FileVo> getFiles(FtpClientPool pool) throws Exception {
        FTPClient ftpClient = pool.getFtpClient();
        String ftpPath = "/";
        if (ftpClient != null) {
            // 开始进行文件上传
            try {
                ftpClient.enterLocalPassiveMode();
                // 修改文件路径
                ftpClient.makeDirectory(ftpPath);
                ftpClient.changeWorkingDirectory(ftpPath);
                // 执行文件传输
                return Arrays.stream(ftpClient.listFiles()).map(f ->
                        new FileVo(f.getName(), DateUtil.formatDateTime(f.getTimestamp().getTime()))
                ).collect(Collectors.toList());
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {// 关闭资源
                pool.returnFTPClient(ftpClient);
            }
        }
        throw new RuntimeException("无可用连接，请先测试连接");
    }

    /**
     * 下载文件
     *
     * @param pool         ftp连接池
     * @param fileName     待下载文件名
     * @param saveFilePath 保存文件路径（带文件名）
     * @author XHP
     * @date 2020年8月14日 上午11:30:04
     */
    public static boolean downLoad(FtpClientPool pool, String fileName, String saveFilePath) throws Exception {
        return downLoad(pool, "/", fileName, saveFilePath);
    }

    /**
     * 下载文件
     *
     * @param pool         ftp连接池
     * @param ftpPath      ftp目录
     * @param fileName     待下载文件名
     * @param saveFilePath 保存文件路径（带文件名）
     * @author XHP
     * @date 2020年8月14日 上午11:30:04
     */
    public static boolean downLoad(FtpClientPool pool, String ftpPath, String fileName, String saveFilePath) throws Exception {
        FTPClient ftpClient = pool.getFtpClient();
        if (ftpClient != null) {
            try (OutputStream os = new BufferedOutputStream(new FileOutputStream(saveFilePath))) {
                ftpClient.enterLocalPassiveMode();
                return ftpClient.retrieveFile(ftpPath + "/" + fileName, os);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 归还连接
                pool.returnFTPClient(ftpClient);
            }
        }
        return false;
    }

    /**
     * 删除文件
     *
     * @param pool ftp连接池
     * @param file 待删除文件名
     * @return
     * @author XHP
     * @date 2020年8月14日 上午11:33:15
     */
    public static Integer deleteFiles(FtpClientPool pool, String file) throws Exception {
        List<String> files = new ArrayList<>(1);
        files.add(file);
        return deleteFiles(pool, "/", files);
    }

    /**
     * 删除文件
     *
     * @param pool  ftp连接池
     * @param files 待删除文件名
     * @return
     * @author XHP
     * @date 2020年8月14日 上午11:33:15
     */
    public static Integer deleteFiles(FtpClientPool pool, List<String> files) throws Exception {
        return deleteFiles(pool, "/", files);
    }

    /**
     * 删除文件
     *
     * @param pool    ftp连接池
     * @param ftpPath ftp目录
     * @param files   待删除文件名
     * @return
     * @author XHP
     * @date 2020年8月14日 上午11:33:15
     */
    public static Integer deleteFiles(FtpClientPool pool, String ftpPath, List<String> files) throws Exception {
        FTPClient ftpClient = pool.getFtpClient();
        if (ftpClient != null) {
            try {
                int count = 0;
                ftpClient.enterLocalPassiveMode();
                ftpClient.changeWorkingDirectory(ftpPath);
                for (String file : files) {
                    if (ftpClient.deleteFile(file)) {
                        count++;
                    }
                }
                return count;
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                // 归还连接
                pool.returnFTPClient(ftpClient);
            }
        }
        throw new RuntimeException("无可用连接，请先测试连接");
    }

}
